"""
恐贪指标业务服务层
整合数据获取和计算服务，提供完整的业务功能
面向应用层提供统一的恐贪指标服务接口
"""

import pandas as pd
import numpy as np
import asyncio
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Union
import logging
import os
from decimal import Decimal
from dotenv import load_dotenv

# 导入LongPort API
from longport.openapi import QuoteContext, Config, Period, AdjustType

# 导入数据库服务
try:
    from database.service import db_service
    from database.models import StockFearGreed
    DATABASE_AVAILABLE = True
except ImportError:
    DATABASE_AVAILABLE = False
    db_service = None
    StockFearGreed = None

# 导入计算处理器
from .fear_greed_processor import fear_greed_processor, ROUND_PRECISION

# 加载环境变量
load_dotenv()

logger = logging.getLogger(__name__)


class FearGreedService:
    """
    恐贪指标业务服务类
    整合数据获取和计算功能，提供完整的业务服务
    """
    
    def __init__(self):
        """初始化业务服务"""
        self.processor = fear_greed_processor
        self._setup_longport_client()
        
    def _setup_longport_client(self):
        """设置长桥API客户端"""
        try:
            # 从环境变量获取LongPort配置
            self.app_key = os.getenv('LONGPORT_APP_KEY')
            self.app_secret = os.getenv('LONGPORT_APP_SECRET')
            self.access_token = os.getenv('LONGPORT_ACCESS_TOKEN')
            
            if not all([self.app_key, self.app_secret, self.access_token]):
                logger.warning("LongPort API配置不完整，部分功能可能受限")
                self.longport_available = False
                return
            
            # 初始化LongPort客户端
            self.config = Config(
                app_key=self.app_key,
                app_secret=self.app_secret,
                access_token=self.access_token
            )
            self.longport_available = True
            logger.info("LongPort API客户端初始化成功")
            
        except Exception as e:
            logger.error(f"LongPort API客户端初始化失败: {e}")
            self.longport_available = False
    
    async def calculate_fear_greed_index(self, symbol: str) -> Dict:
        """
        计算单个股票的恐贪指标
        
        Args:
            symbol: 股票代码
            
        Returns:
            包含恐贪指标计算结果的字典
        """
        try:
            logger.info(f"开始计算 {symbol} 的恐贪指标")
            
            # 优先从数据库获取最新计算结果
            if DATABASE_AVAILABLE:
                latest = await db_service.get_stock_fear_greed(symbol, 1)
                if latest and latest[0].fear_greed_index != '50.000':  # Assuming default means not calculated
                    result = latest[0].to_api_format()
                    result['symbol'] = symbol
                    result['current_price'] = float(latest[0].close_price)
                    result['data_date'] = latest[0].date.strftime('%Y-%m-%d')
                    result['data_source'] = 'database'
                    logger.info(f"✅ 从数据库获取 {symbol} 的恐贪指标")
                    return result
            
            # 如果数据库没有，获取股票数据
            df = await self.get_stock_data(symbol, 360)
            
            if df.empty or len(df) < 50:
                raise ValueError(f"股票 {symbol} 数据不足，无法计算恐贪指标")
            
            # 计算恐贪指标
            result = self.processor.calculate_fear_greed_index_from_data(df, symbol)
            
            # 添加股票相关信息
            result['symbol'] = symbol
            result['current_price'] = float(round(df['Close'].iloc[-1], ROUND_PRECISION))
            result['data_date'] = df.index[-1].strftime('%Y-%m-%d')
            result['data_source'] = self._get_data_source_info()
            
            # 保存到数据库
            if DATABASE_AVAILABLE:
                record = StockFearGreed(
                    symbol=symbol,
                    date=df.index[-1].date(),
                    open_price=str(df['Open'].iloc[-1]),
                    high_price=str(df['High'].iloc[-1]),
                    low_price=str(df['Low'].iloc[-1]),
                    close_price=str(df['Close'].iloc[-1]),
                    volume=str(int(df['Volume'].iloc[-1])),
                    fear_greed_index=str(result['fear_greed_index']),
                    sentiment=result['sentiment'],
                    investment_advice=result['investment_advice'],
                    rsi=str(result['components'].get('rsi', 50.0)),
                    volatility=str(result['components'].get('volatility', 0.0)),
                    volume_ratio=str(result['components'].get('volume_ratio', 1.0)),
                    put_call_ratio=str(result['components'].get('put_call_ratio', 1.0))
                )
                await db_service.save_stock_fear_greed([record])
            
            logger.info(f"成功计算 {symbol} 的恐贪指标: {result['fear_greed_index']}")
            return result
            
        except Exception as e:
            logger.error(f"计算 {symbol} 恐贪指标失败: {str(e)}")
            raise
    
    async def calculate_batch_fear_greed_index(self, symbols: List[str]) -> Dict[str, Dict]:
        """
        批量计算多个股票的恐贪指标
        
        Args:
            symbols: 股票代码列表
            
        Returns:
            股票代码到恐贪指标结果的映射
        """
        try:
            logger.info(f"开始批量计算恐贪指标，股票数量: {len(symbols)}")
            
            result = {}
            success_count = 0
            error_count = 0
            
            # 批量获取股票数据
            logger.info(f"开始批量获取 {len(symbols)} 个股票的数据")
            stocks_data = await self.get_multiple_stocks_data(symbols, 360)
            
            # 并发计算恐贪指标
            async def calculate_single_stock(symbol: str) -> tuple:
                try:
                    df = stocks_data.get(symbol, pd.DataFrame())
                    
                    # 放宽数据要求：只要有数据就尝试计算
                    if df.empty:
                        logger.warning(f"股票 {symbol} 没有数据，跳过计算")
                        return symbol, self._create_error_result(symbol, "无数据"), False
                    
                    if len(df) < 20:  # 降低最小数据要求
                        logger.warning(f"股票 {symbol} 数据不足（{len(df)}条），但尝试计算")
                    
                    # 计算恐贪指标
                    calculation_result = self.processor.calculate_fear_greed_index_from_data(df, symbol)
                    
                    # 添加股票相关信息
                    calculation_result['symbol'] = symbol
                    calculation_result['current_price'] = float(round(df['Close'].iloc[-1], ROUND_PRECISION))
                    calculation_result['data_date'] = df.index[-1].strftime('%Y-%m-%d')
                    calculation_result['data_count'] = len(df)
                    
                    logger.debug(f"✅ 成功计算 {symbol} 的恐贪指标")
                    return symbol, calculation_result, True
                    
                except Exception as e:
                    logger.error(f"计算股票 {symbol} 恐贪指标失败: {str(e)}")
                    return symbol, self._create_error_result(symbol, str(e)), False
            
            # 并发执行所有计算任务
            calculation_tasks = [calculate_single_stock(symbol) for symbol in symbols]
            calculation_results = await asyncio.gather(*calculation_tasks, return_exceptions=True)
            
            # 处理计算结果
            for calc_result in calculation_results:
                if isinstance(calc_result, Exception):
                    error_count += 1
                    logger.error(f"计算任务执行异常: {calc_result}")
                    continue
                    
                symbol, calc_data, success = calc_result
                result[symbol] = calc_data
                
                if success:
                    success_count += 1
                else:
                    error_count += 1
            
            logger.info(f"批量计算完成，成功: {success_count} 个，失败: {error_count} 个，总计: {len(symbols)} 个")
            return result
            
        except Exception as e:
            logger.error(f"批量计算恐贪指标失败: {str(e)}")
            raise
    
    async def get_calculated_data_from_database(self, symbol: str, days: int = 360) -> List[Dict]:
        """
        直接从数据库获取已计算好的恐贪指标数据
        
        这个方法专门用于快速获取数据库中已存在的计算结果，
        不会进行任何API调用或重新计算。
        
        Args:
            symbol: 股票代码
            days: 获取天数
            
        Returns:
            历史恐贪指标列表，如果数据库中没有数据则返回空列表
        """
        try:
            logger.info(f"直接从数据库获取 {symbol} 的已计算数据，天数: {days}")
            
            if not DATABASE_AVAILABLE:
                logger.warning(f"⚠️ 数据库不可用，无法获取 {symbol} 的数据")
                return []
            
            # 直接从数据库获取数据
            db_history = await db_service.get_stock_fear_greed(symbol, days)
            
            if db_history and len(db_history) > 0:
                logger.info(f"✅ 成功从数据库获取 {symbol} 的已计算数据，共 {len(db_history)} 条记录")
                return [history.to_api_format() for history in db_history]
            else:
                logger.info(f"ℹ️ 数据库中 {symbol} 暂无已计算的数据")
                return []
                
        except Exception as e:
            logger.error(f"❌ 从数据库获取 {symbol} 已计算数据失败: {str(e)}")
            return []

    async def get_fear_greed_history(self, symbol: str, days: int = 360, force_recalculate: bool = False) -> List[Dict]:
        """
        获取恐贪指标历史数据
        
        策略：优先从数据库获取，如果没有则计算并保存
        
        Args:
            symbol: 股票代码
            days: 获取天数
            force_recalculate: 强制重新计算，忽略数据库中的现有数据
            
        Returns:
            历史恐贪指标列表
        """
        try:
            logger.info(f"开始获取 {symbol} 的恐贪指标历史数据，天数: {days}, 强制重新计算: {force_recalculate}")
            
            # 优先从数据库获取历史数据
            if DATABASE_AVAILABLE and not force_recalculate:
                db_history = await db_service.get_stock_fear_greed(symbol, days)
                
                if db_history and len(db_history) > 0:
                    logger.info(f"✅ 从数据库获取到 {symbol} 的历史数据，共 {len(db_history)} 条记录")
                    return [history.to_api_format() for history in db_history]
                else:
                    logger.info(f"ℹ️ 数据库中 {symbol} 暂无历史数据，开始计算...")
                    # 如果数据库没有数据，计算并保存
                    calculated_data = await self.calculate_and_save_fear_greed_history(symbol, days)
                    if calculated_data:
                        logger.info(f"✅ 计算并保存 {symbol} 历史数据成功，共 {len(calculated_data)} 条记录")
                        return calculated_data
                    else:
                        logger.warning(f"⚠️ {symbol} 计算历史数据失败")
                        return []
            else:
                if force_recalculate:
                    logger.info(f"🔄 强制重新计算 {symbol} 的历史数据")
                else:
                    logger.warning(f"⚠️ 数据库不可用，尝试实时计算")
                
                # 强制重新计算或数据库不可用时，实时计算
                calculated_data = await self._calculate_fear_greed_history(symbol, days)
                if calculated_data and DATABASE_AVAILABLE:
                    # 如果计算成功且数据库可用，保存到数据库
                    await self.calculate_and_save_fear_greed_history(symbol, days)
                return calculated_data
            
        except Exception as e:
            logger.error(f"❌ 获取 {symbol} 恐贪指标历史数据失败: {str(e)}")
            return []
    
    async def _calculate_fear_greed_history(self, symbol: str, days: int) -> List[Dict]:
        """实时计算恐贪指标历史数据"""
        try:
            # 获取足够的历史数据用于计算
            df = await self.get_stock_data(symbol, days + 100)
            
            if df.empty or len(df) < 50:
                raise ValueError(f"股票 {symbol} 数据不足，无法计算历史恐贪指标")
            
            # 使用处理器进行历史计算
            history_results = self.processor.calculate_historical_fear_greed(df, symbol)
            
            # 返回指定天数的数据
            result_data = history_results[-days:] if len(history_results) > days else history_results
            
            logger.info(f"实时计算完成，{symbol} 历史恐贪指标共 {len(result_data)} 条记录")
            return result_data
            
        except Exception as e:
            logger.error(f"实时计算 {symbol} 历史恐贪指标失败: {str(e)}")
            return []
    
    async def calculate_and_save_fear_greed_history(self, symbol: str, days: int = 360) -> List[Dict]:
        """
        计算恐贪指标历史数据并保存到数据库
        
        Args:
            symbol: 股票代码
            days: 计算天数
            
        Returns:
            计算并保存的历史恐贪指标列表
        """
        try:
            logger.info(f"开始计算并保存 {symbol} 的恐贪指标历史数据，天数: {days}")
            
            # 获取原始股票数据
            df = await self.get_stock_data(symbol, days + 100)
            
            if df.empty or len(df) < 50:
                logger.warning(f"⚠️ {symbol} 原始数据不足，无法计算历史恐贪指标")
                return []
            
            # 实时计算历史数据
            calculated_history = await self._calculate_fear_greed_history(symbol, days)
            
            if not calculated_history:
                logger.warning(f"⚠️ {symbol} 计算历史数据为空")
                return []
            
            # 保存计算结果到数据库
            if DATABASE_AVAILABLE:
                try:
                    # 转换为数据库模型格式
                    db_records = []
                    for record in calculated_history:
                        # 处理 NaN 值
                        def safe_str(value, default='0.0'):
                            if value is None or np.isnan(value):
                                return default
                            return str(value)
                        
                        # 获取对应日期的原始OHLCV数据
                        record_date = datetime.strptime(record['date'], '%Y-%m-%d').date()
                        
                        # 尝试多种方式匹配原始数据
                        original_data = None
                        
                        # 方法1: 直接匹配date对象
                        if record_date in df.index:
                            original_data = df.loc[record_date]
                        # 方法2: 使用pd.Timestamp匹配
                        elif pd.Timestamp(record_date) in df.index:
                            original_data = df.loc[pd.Timestamp(record_date)]
                        # 方法3: 使用字符串匹配
                        else:
                            date_str = record_date.strftime('%Y-%m-%d')
                            # 确保索引是DatetimeIndex
                            if not isinstance(df.index, pd.DatetimeIndex):
                                df.index = pd.to_datetime(df.index)
                            date_matches = df[df.index.strftime('%Y-%m-%d') == date_str]
                            if not date_matches.empty:
                                original_data = date_matches.iloc[0]
                        
                        # 优先使用计算器中返回的完整OHLCV数据
                        if 'open_price' in record and 'high_price' in record and 'low_price' in record and 'volume' in record:
                            # 使用计算器返回的完整数据
                            open_price = safe_str(record['open_price'])
                            high_price = safe_str(record['high_price'])
                            low_price = safe_str(record['low_price'])
                            close_price = safe_str(record['close_price'])
                            volume = safe_str(record['volume'])
                        elif original_data is not None and not original_data.empty:
                            # 如果计算器没有返回完整数据，尝试从原始DataFrame获取
                            open_price = safe_str(original_data['Open'])
                            high_price = safe_str(original_data['High'])
                            low_price = safe_str(original_data['Low'])
                            close_price = safe_str(original_data['Close'])
                            volume = safe_str(original_data['Volume'])
                        else:
                            # 如果都找不到，使用收盘价作为默认值
                            open_price = safe_str(record.get('open_price', record.get('close_price', '0.0')))
                            high_price = safe_str(record.get('high_price', record.get('close_price', '0.0')))
                            low_price = safe_str(record.get('low_price', record.get('close_price', '0.0')))
                            close_price = safe_str(record.get('close_price', '0.0'))
                            volume = safe_str(record.get('volume', '0'))
                        
                        db_records.append(StockFearGreed(
                            symbol=symbol,
                            date=record_date,
                            open_price=open_price,
                            high_price=high_price,
                            low_price=low_price,
                            close_price=close_price,
                            volume=volume,
                            fear_greed_index=safe_str(record['fear_greed_index'], '0.0'),
                            sentiment=record['sentiment'],
                            investment_advice=record['investment_advice'],
                            rsi=safe_str(record['rsi'], '50.0'),
                            volatility=safe_str(record['volatility'], '0.0'),
                            volume_ratio=safe_str(record['volume_ratio'], '1.0'),
                            put_call_ratio=safe_str(record['put_call_ratio'], '1.0')
                        ))
                    
                    logger.info(f"📊 准备保存 {symbol} 的 {len(db_records)} 条恐贪指数数据到数据库...")
                    saved_count = await db_service.save_stock_fear_greed(db_records)
                    
                    if saved_count > 0:
                        logger.info(f"✅ 成功保存 {symbol} 恐贪指数历史数据到数据库，共 {saved_count} 条记录")
                    else:
                        logger.warning(f"⚠️ {symbol} 数据保存失败，返回数量为0")
                    
                except Exception as save_error:
                    logger.error(f"❌ 保存 {symbol} 恐贪指数历史数据到数据库失败: {save_error}")
                    logger.error(f"错误详情: {type(save_error).__name__}: {str(save_error)}")
                    return []
            else:
                logger.warning(f"⚠️ 数据库不可用，无法保存计算结果")
            
            return calculated_history
            
        except Exception as e:
            logger.error(f"❌ 计算并保存 {symbol} 恐贪指标历史数据失败: {str(e)}")
            return []
    
    async def precompute_history_data(self, symbol: str, days: int = 360) -> Dict:
        """
        预计算历史数据（后台任务）
        
        Args:
            symbol: 股票代码
            days: 计算天数
            
        Returns:
            预计算结果
        """
        try:
            logger.info(f"开始预计算 {symbol} 的历史数据，天数: {days}")
            
            # 检查数据库中是否已有足够数据
            if DATABASE_AVAILABLE:
                existing_data = await db_service.get_stock_fear_greed(symbol, days)
                if existing_data and len(existing_data) >= min(50, days // 2):
                    logger.info(f"✅ {symbol} 数据库中已有足够的历史数据，无需重新计算")
                    return {
                        'success': True,
                        'message': f'{symbol} 数据库中已有 {len(existing_data)} 条历史数据',
                        'data_count': len(existing_data)
                    }
            
            # 计算并保存历史数据
            calculated_history = await self.calculate_and_save_fear_greed_history(symbol, days)
            
            if calculated_history:
                return {
                    'success': True,
                    'message': f'{symbol} 历史数据计算完成，共 {len(calculated_history)} 条记录',
                    'data_count': len(calculated_history)
                }
            else:
                return {
                    'success': False,
                    'message': f'{symbol} 历史数据计算失败',
                    'data_count': 0
                }
                
        except Exception as e:
            logger.error(f"❌ 预计算 {symbol} 历史数据失败: {str(e)}")
            return {
                'success': False,
                'message': f'预计算失败: {str(e)}',
                'data_count': 0
            }
    
    async def analyze_stock_trend(self, symbol: str, days: int = 30) -> Dict:
        """
        分析股票趋势变化
        
        Args:
            symbol: 股票代码
            days: 分析天数
            
        Returns:
            趋势分析结果
        """
        try:
            logger.info(f"开始分析 {symbol} 的趋势变化，天数: {days}")
            
            # 获取历史数据
            df = await self.get_stock_data(symbol, days + 50)
            
            if df.empty or len(df) < 20:
                raise ValueError(f"股票 {symbol} 数据不足，无法进行趋势分析")
            
            # 分析最近的恐贪指标变化
            analysis = {
                'symbol': symbol,
                'analysis_date': datetime.now().isoformat(),
                'price_changes': [],
                'fear_greed_changes': [],
                'summary': {}
            }
            
            # 分析最近days天的变化
            start_index = max(20, len(df) - days)
            for i in range(start_index, len(df)):
                daily_data = df.iloc[:i+1].copy()
                if len(daily_data) >= 20:
                    try:
                        # 计算当日指标
                        result = self.processor.calculate_fear_greed_index_from_data(daily_data, symbol)
                        
                        # 记录变化
                        date_str = daily_data.index[-1].strftime('%Y-%m-%d')
                        price = daily_data['Close'].iloc[-1]
                        
                        analysis['price_changes'].append({
                            'date': date_str,
                            'price': round(price, 3),
                            'change': round((price - daily_data['Close'].iloc[-2]) / daily_data['Close'].iloc[-2] * 100, 2) if i > start_index else 0
                        })
                        
                        analysis['fear_greed_changes'].append({
                            'date': date_str,
                            'fear_greed_index': result['fear_greed_index'],
                            'sentiment': result['sentiment'],
                            'components': result['components']
                        })
                    except Exception as e:
                        logger.warning(f"计算 {symbol} 第 {i} 天的指标失败: {e}")
                        continue
            
            # 生成分析摘要
            if analysis['price_changes'] and analysis['fear_greed_changes']:
                price_change = analysis['price_changes'][-1]['change']
                current_fg = analysis['fear_greed_changes'][-1]['fear_greed_index']
                current_sentiment = analysis['fear_greed_changes'][-1]['sentiment']
                
                analysis['summary'] = {
                    'price_change_pct': price_change,
                    'current_fear_greed_index': current_fg,
                    'current_sentiment': current_sentiment,
                    'data_points': len(analysis['fear_greed_changes'])
                }
            
            logger.info(f"完成 {symbol} 趋势分析，数据点: {len(analysis['fear_greed_changes'])}")
            return analysis
            
        except Exception as e:
            logger.error(f"分析 {symbol} 趋势失败: {str(e)}")
            raise
    
    def _create_error_result(self, symbol: str, error_message: str) -> Dict:
        """创建错误结果"""
        return {
            'symbol': symbol,
            'error': error_message,
            'fear_greed_index': 0,
            'sentiment': '计算失败',
            'investment_advice': '无法提供建议',
            'current_price': 0,
            'timestamp': datetime.now().isoformat()
        }
    
    async def get_stock_data(self, symbol: str, period_days: int = 360) -> pd.DataFrame:
        """
        获取股票历史数据
        
        优先级：数据库 -> LongPort API -> 自动保存到数据库
        
        Args:
            symbol: 股票代码
            period_days: 获取天数
            
        Returns:
            包含OHLCV数据的DataFrame，列名为['Open', 'High', 'Low', 'Close', 'Volume']
        """
        try:
            logger.debug(f"开始获取 {symbol} 的数据，请求天数: {period_days}")
            
            # 第一优先级：从数据库获取数据
            if DATABASE_AVAILABLE and db_service:
                logger.debug(f"尝试从数据库获取 {symbol} 的数据")
                df = await db_service.get_stock_data_as_dataframe(symbol, period_days)
                
                if not df.empty and len(df) >= 10:  # 降低数据要求
                    logger.info(f"✅ 从数据库成功获取 {symbol} 的数据，共 {len(df)} 天")
                    return df
                else:
                    logger.warning(f"⚠️ 数据库中 {symbol} 的数据不足（{len(df) if not df.empty else 0}条），尝试API获取")
            
            # 第二优先级：从LongPort API获取数据
            if self.longport_available:
                logger.debug(f"尝试从LongPort API获取 {symbol} 的数据")
                df = await self._get_data_from_longport(symbol, period_days)
                
                if not df.empty and len(df) >= 10:  # 降低数据要求
                    logger.info(f"✅ 从LongPort API成功获取 {symbol} 的数据，共 {len(df)} 天")
                    
                    # 自动保存到数据库 (only raw data, calculations happen elsewhere)
                    if DATABASE_AVAILABLE and db_service:
                        try:
                            # Create StockFearGreed records with default calculated fields
                            records = []
                            for date, row in df.iterrows():
                                records.append(StockFearGreed(
                                    symbol=symbol,
                                    date=date.date(),
                                    open_price=str(row['Open']),
                                    high_price=str(row['High']),
                                    low_price=str(row['Low']),
                                    close_price=str(row['Close']),
                                    volume=str(int(row['Volume']))
                                ))
                            saved_count = await db_service.save_stock_fear_greed(records)
                            logger.info(f"💾 自动保存 {symbol} 数据到数据库，共 {saved_count} 条记录")
                        except Exception as save_error:
                            logger.warning(f"⚠️ 保存数据到数据库失败: {save_error}")
                    
                    return df
                else:
                    logger.warning(f"⚠️ LongPort API返回的数据不足（{len(df) if not df.empty else 0}条）")
            else:
                logger.warning(f"⚠️ LongPort API不可用，无法获取 {symbol} 的数据")
            
            # 所有数据源都不可用
            logger.error(f"❌ 所有数据源都不可用，无法获取 {symbol} 的数据")
            return pd.DataFrame()
            
        except Exception as e:
            logger.error(f"❌ 获取股票 {symbol} 数据失败: {str(e)}")
            return pd.DataFrame()
    
    async def _get_data_from_database(self, symbol: str, period_days: int) -> pd.DataFrame:
        """从数据库获取股票数据"""
        try:
            df = await db_service.get_stock_data_as_dataframe(symbol, period_days)
            
            if not df.empty:
                logger.debug(f"数据库返回 {len(df)} 条记录")
                logger.debug(f"数据范围: {df.index[0]} 至 {df.index[-1]}")
                logger.debug(f"最新价格: {df['Close'].iloc[-1]}")
            
            return df
            
        except Exception as e:
            logger.error(f"从数据库获取数据失败: {e}")
            return pd.DataFrame()
    
    async def _get_data_from_longport(self, symbol: str, period_days: int) -> pd.DataFrame:
        """从LongPort API获取股票数据"""
        try:
            ctx = QuoteContext(self.config)
            
            # 获取日线数据 - 使用前复权数据
            candlesticks = ctx.candlesticks(
                symbol=symbol,
                period=Period.Day,
                count=period_days,
                adjust_type=AdjustType.ForwardAdjust
            )
            
            if not candlesticks:
                logger.warning(f"LongPort API未返回 {symbol} 的数据")
                return pd.DataFrame()
            
            # 转换为DataFrame
            df = self._convert_candlesticks_to_dataframe(candlesticks)
            
            logger.debug(f"LongPort API返回 {len(df)} 条记录")
            if not df.empty:
                logger.debug(f"数据范围: {df.index[0]} 至 {df.index[-1]}")
                logger.debug(f"最新价格: {df['Close'].iloc[-1]}")
            
            return df
            
        except Exception as e:
            logger.error(f"从LongPort API获取数据失败: {e}")
            return pd.DataFrame()
    
    def _convert_candlesticks_to_dataframe(self, candlesticks) -> pd.DataFrame:
        """将K线数据转换为DataFrame"""
        try:
            data = []
            for candle in candlesticks:
                data.append({
                    'date': candle.timestamp,
                    'open': float(candle.open) if isinstance(candle.open, Decimal) else candle.open,
                    'high': float(candle.high) if isinstance(candle.high, Decimal) else candle.high,
                    'low': float(candle.low) if isinstance(candle.low, Decimal) else candle.low,
                    'close': float(candle.close) if isinstance(candle.close, Decimal) else candle.close,
                    'volume': int(candle.volume) if isinstance(candle.volume, Decimal) else candle.volume,
                    'turnover': float(candle.turnover) if isinstance(candle.turnover, Decimal) else candle.turnover
                })
            
            df = pd.DataFrame(data)
            df['date'] = pd.to_datetime(df['date'])
            df.set_index('date', inplace=True)
            
            # 重命名列以符合标准格式
            df.rename(columns={
                'open': 'Open',
                'high': 'High', 
                'low': 'Low',
                'close': 'Close',
                'volume': 'Volume',
                'turnover': 'Turnover'
            }, inplace=True)
            
            return df
            
        except Exception as e:
            logger.error(f"转换K线数据失败: {e}")
            return pd.DataFrame()
    
    def _is_data_sufficient(self, df: pd.DataFrame, period_days: int) -> bool:
        """检查数据是否足够"""
        if df.empty:
            return False
        
        # 放宽数据量检查：至少需要10天数据，或者请求天数的一半（取较小值）
        min_required = max(10, min(period_days // 2, 50))
        actual_count = len(df)
        
        logger.debug(f"数据充足性检查: 需要{min_required}条，实际{actual_count}条")
        return actual_count >= min_required
    
    async def get_multiple_stocks_data(self, symbols: List[str], period_days: int = 360) -> Dict[str, pd.DataFrame]:
        """
        批量获取多个股票的数据（并发优化版本）
        
        Args:
            symbols: 股票代码列表
            period_days: 获取天数
            
        Returns:
            股票代码到DataFrame的映射
        """
        result = {}
        success_count = 0
        error_count = 0
        
        logger.info(f"开始并发获取 {len(symbols)} 个股票的数据")
        
        # 创建并发任务
        async def get_single_stock_data(symbol: str) -> tuple:
            try:
                logger.debug(f"正在获取 {symbol} 的数据...")
                df = await self.get_stock_data(symbol, period_days)
                
                if not df.empty:
                    logger.debug(f"✅ 成功获取 {symbol} 的数据，共 {len(df)} 条记录")
                    return symbol, df, True
                else:
                    logger.warning(f"⚠️ 获取 {symbol} 数据失败，返回空DataFrame")
                    return symbol, pd.DataFrame(), False
                    
            except Exception as e:
                logger.error(f"❌ 获取股票 {symbol} 数据失败: {e}")
                return symbol, pd.DataFrame(), False
        
        # 并发执行所有任务
        tasks = [get_single_stock_data(symbol) for symbol in symbols]
        results = await asyncio.gather(*tasks, return_exceptions=True)
        
        # 处理结果
        for result_item in results:
            if isinstance(result_item, Exception):
                error_count += 1
                logger.error(f"任务执行异常: {result_item}")
                continue
                
            symbol, df, success = result_item
            result[symbol] = df
            
            if success:
                success_count += 1
            else:
                error_count += 1
        
        logger.info(f"并发获取数据完成，成功: {success_count} 个，失败: {error_count} 个，总计: {len(symbols)} 个股票")
        return result
    
    def get_data_source_status(self) -> Dict[str, bool]:
        """
        获取各数据源的状态
        
        Returns:
            数据源状态字典
        """
        return {
            'database': DATABASE_AVAILABLE and db_service is not None,
            'longport_api': self.longport_available,
            'mock_data': False  # 已移除模拟数据
        }
    
    def _get_data_source_info(self) -> Dict:
        """获取数据源信息"""
        return self.get_data_source_status()
    
    def get_service_status(self) -> Dict:
        """
        获取服务状态
        
        Returns:
            服务状态信息
        """
        return {
            'service_name': 'FearGreedService',
            'status': 'running',
            'data_sources': self._get_data_source_info(),
            'processor': 'available',
            'timestamp': datetime.now().isoformat()
        }

    async def fix_stock_fear_greed_data(self, symbol: str, force_recalculate: bool = True, days: int = 365) -> Dict:
        """
        修复单个股票的恐贪指数数据
        
        Args:
            symbol: 股票代码
            force_recalculate: 是否强制重新计算
            days: 重新计算的天数
            
        Returns:
            修复结果
        """
        try:
            logger.info(f"开始修复 {symbol} 的恐贪指数数据")
            
            # 先检查数据质量
            quality_report = await self.check_data_quality(symbol)
            
            if not quality_report['needs_fix'] and not force_recalculate:
                logger.info(f"✅ {symbol} 数据质量良好，无需修复")
                return {
                    "symbol": symbol,
                    "status": "no_fix_needed",
                    "quality_report": quality_report,
                    "message": "数据质量良好，无需修复"
                }
            
            # 强制重新计算并保存
            logger.info(f"🔄 强制重新计算 {symbol} 的恐贪指数数据")
            calculated_history = await self.calculate_and_save_fear_greed_history(symbol, days)
            
            if calculated_history:
                # 再次检查数据质量
                new_quality_report = await self.check_data_quality(symbol)
                
                return {
                    "symbol": symbol,
                    "status": "fixed",
                    "original_quality": quality_report,
                    "new_quality": new_quality_report,
                    "records_updated": len(calculated_history),
                    "message": f"成功修复 {symbol} 的恐贪指数数据，更新了 {len(calculated_history)} 条记录"
                }
            else:
                return {
                    "symbol": symbol,
                    "status": "failed",
                    "quality_report": quality_report,
                    "message": f"修复 {symbol} 失败，无法计算新的恐贪指数数据"
                }
                
        except Exception as e:
            logger.error(f"修复 {symbol} 恐贪指数数据失败: {str(e)}")
            return {
                "symbol": symbol,
                "status": "error",
                "error": str(e),
                "message": f"修复 {symbol} 时发生错误: {str(e)}"
            }

    async def batch_fix_stock_fear_greed_data(self, symbols: List[str], force_recalculate: bool = True, days: int = 365) -> Dict[str, Dict]:
        """
        批量修复多个股票的恐贪指数数据（并发同步处理）
        
        Args:
            symbols: 股票代码列表
            force_recalculate: 是否强制重新计算
            days: 重新计算的天数
            
        Returns:
            股票代码到修复结果的映射
        """
        try:
            logger.info(f"开始批量修复 {len(symbols)} 个股票的恐贪指数数据")
            
            # 创建并发修复任务
            async def fix_single_stock(symbol: str) -> tuple:
                try:
                    logger.debug(f"开始修复股票 {symbol}")
                    result = await self.fix_stock_fear_greed_data(symbol, force_recalculate, days)
                    return symbol, result
                except Exception as e:
                    logger.error(f"修复股票 {symbol} 时发生异常: {e}")
                    return symbol, {
                        "symbol": symbol,
                        "status": "error",
                        "error": str(e),
                        "message": f"修复 {symbol} 时发生异常: {str(e)}"
                    }
            
            # 并发执行所有修复任务
            fix_tasks = [fix_single_stock(symbol) for symbol in symbols]
            fix_results = await asyncio.gather(*fix_tasks, return_exceptions=True)
            
            # 处理结果
            results = {}
            for fix_result in fix_results:
                if isinstance(fix_result, Exception):
                    logger.error(f"修复任务执行异常: {fix_result}")
                    continue
                    
                symbol, result = fix_result
                results[symbol] = result
            
            # 统计结果
            success_count = sum(1 for result in results.values() if result.get('status') in ['fixed', 'no_fix_needed'])
            error_count = len(symbols) - success_count
            
            logger.info(f"批量修复完成，成功: {success_count} 个，失败: {error_count} 个，总计: {len(symbols)} 个")
            return results
            
        except Exception as e:
            logger.error(f"批量修复恐贪指数数据失败: {str(e)}")
            raise
    
    async def check_data_quality(self, symbol: str) -> Dict:
        """
        检查单个股票的恐贪指数数据质量
        
        Args:
            symbol: 股票代码
            
        Returns:
            数据质量报告
        """
        try:
            logger.info(f"检查 {symbol} 的恐贪指数数据质量")
            
            # 获取数据库中的数据
            db_history = await db_service.get_stock_fear_greed(symbol, 30)  # 检查最近30天
            
            if not db_history:
                return {
                    "symbol": symbol,
                    "needs_fix": True,
                    "reason": "no_data",
                    "data_count": 0,
                    "zero_count": 0,
                    "default_count": 0,
                    "valid_count": 0,
                    "quality_score": 0.0
                }
            
            # 分析数据质量
            total_count = len(db_history)
            zero_count = 0
            default_count = 0
            valid_count = 0
            
            for record in db_history:
                fear_greed_value = record.fear_greed_index
                
                if fear_greed_value == '0.000' or float(fear_greed_value) == 0:
                    zero_count += 1
                elif fear_greed_value == '50.000' or float(fear_greed_value) == 50:
                    default_count += 1
                else:
                    valid_count += 1
            
            # 计算质量分数
            quality_score = valid_count / total_count if total_count > 0 else 0.0
            
            # 判断是否需要修复
            needs_fix = (
                quality_score < 0.8 or  # 有效数据少于80%
                zero_count > total_count * 0.5 or  # 零值超过50%
                default_count > total_count * 0.3  # 默认值超过30%
            )
            
            reason = "good"
            if quality_score < 0.8:
                reason = "low_quality"
            elif zero_count > total_count * 0.5:
                reason = "too_many_zeros"
            elif default_count > total_count * 0.3:
                reason = "too_many_defaults"
            
            return {
                "symbol": symbol,
                "needs_fix": needs_fix,
                "reason": reason,
                "data_count": total_count,
                "zero_count": zero_count,
                "default_count": default_count,
                "valid_count": valid_count,
                "quality_score": quality_score,
                "sample_values": [
                    {
                        "date": record.date.strftime('%Y-%m-%d'),
                        "fear_greed_index": record.fear_greed_index,
                        "sentiment": record.sentiment
                    }
                    for record in db_history[:5]  # 显示前5条记录作为样本
                ]
            }
            
        except Exception as e:
            logger.error(f"检查 {symbol} 数据质量失败: {str(e)}")
            return {
                "symbol": symbol,
                "needs_fix": True,
                "reason": "check_error",
                "error": str(e),
                "data_count": 0,
                "zero_count": 0,
                "default_count": 0,
                "valid_count": 0,
                "quality_score": 0.0
            }


# 创建全局实例
fear_greed_service = FearGreedService()
